"""
商品成品相关数据模型

包括成品表和成品-素材关联表等模型。
"""

from datetime import datetime
from typing import Dict, Any, Optional, List
import json
import enum

from sqlalchemy import Column, Integer, String, Float, Text, Boolean, ForeignKey, Index, DateTime, Enum
from sqlalchemy.orm import relationship, backref

from .base import BaseModel, JSONField


class OutputStatus(enum.Enum):
    """成品状态枚举"""
    DRAFT = "draft"              # 草稿
    PROCESSING = "processing"    # 制作中
    COMPLETED = "completed"      # 已完成
    PUBLISHED = "published"      # 已发布
    ARCHIVED = "archived"        # 已归档
    FAILED = "failed"           # 制作失败


class OutputType(enum.Enum):
    """成品类型枚举"""
    VIDEO = "video"             # 视频
    IMAGE_SET = "image_set"     # 图片集
    ANIMATION = "animation"     # 动画
    SLIDESHOW = "slideshow"     # 幻灯片
    OTHER = "other"             # 其他


class QualityLevel(enum.Enum):
    """质量等级枚举"""
    LOW = "low"                 # 低质量
    MEDIUM = "medium"           # 中等质量
    HIGH = "high"               # 高质量
    PREMIUM = "premium"         # 优质


class ProductOutput(BaseModel):
    """
    成品表
    
    存储基于模板和素材制作的最终成品。
    """
    
    __tablename__ = 'product_outputs'
    
    # 关联商品
    product_id = Column(Integer, ForeignKey('products.id'), nullable=False)
    product = relationship("Product", back_populates="outputs")
    
    # 基本信息
    name = Column(String(255), nullable=False, index=True)
    title = Column(String(500), nullable=True)
    description = Column(Text, nullable=True)
    
    # 成品标识
    output_id = Column(String(100), unique=True, nullable=False, index=True)  # 成品唯一标识
    version = Column(String(50), nullable=True)                               # 版本号
    
    # 类型和状态
    output_type = Column(Enum(OutputType), nullable=False, default=OutputType.VIDEO)
    status = Column(Enum(OutputStatus), nullable=False, default=OutputStatus.DRAFT)
    quality_level = Column(Enum(QualityLevel), nullable=False, default=QualityLevel.MEDIUM)
    
    # 文件信息
    file_path = Column(String(500), nullable=True)          # 成品文件路径
    file_size = Column(Integer, nullable=True)              # 文件大小(字节)
    file_hash = Column(String(64), nullable=True, index=True)  # 文件哈希
    mime_type = Column(String(100), nullable=True)          # MIME类型
    
    # 技术规格
    width = Column(Integer, nullable=True)                  # 宽度
    height = Column(Integer, nullable=True)                 # 高度
    duration = Column(Float, nullable=True)                 # 时长(秒)
    fps = Column(Float, nullable=True)                      # 帧率
    bitrate = Column(Integer, nullable=True)                # 比特率
    codec = Column(String(100), nullable=True)              # 编码格式
    
    # 制作信息
    template_used = Column(String(255), nullable=True)      # 使用的模板
    materials_count = Column(Integer, default=0)            # 使用的素材数量
    processing_time = Column(Float, nullable=True)          # 制作耗时(秒)
    
    # 制作参数
    render_settings = Column(JSONField, nullable=True)      # 渲染设置
    export_settings = Column(JSONField, nullable=True)      # 导出设置
    
    # 质量评估
    quality_score = Column(Float, nullable=True)            # 质量评分 (0-1)
    technical_metrics = Column(JSONField, nullable=True)    # 技术指标
    
    # 审核信息
    is_approved = Column(Boolean, default=False)            # 是否审核通过
    approved_by = Column(String(100), nullable=True)        # 审核人
    approved_at = Column(DateTime, nullable=True)           # 审核时间
    approval_notes = Column(Text, nullable=True)            # 审核备注
    
    # 发布信息
    is_published = Column(Boolean, default=False)           # 是否已发布
    published_at = Column(DateTime, nullable=True)          # 发布时间
    published_to = Column(JSONField, nullable=True)         # 发布平台列表
    
    # 使用统计
    view_count = Column(Integer, default=0)                 # 查看次数
    download_count = Column(Integer, default=0)             # 下载次数
    share_count = Column(Integer, default=0)                # 分享次数
    
    # 标签和分类
    tags = Column(JSONField, nullable=True)                 # 标签列表
    category = Column(String(100), nullable=True, index=True)
    keywords = Column(Text, nullable=True)                  # 关键词
    
    # 制作记录
    creation_started_at = Column(DateTime, nullable=True)   # 开始制作时间
    creation_completed_at = Column(DateTime, nullable=True) # 完成制作时间
    creation_error = Column(Text, nullable=True)            # 制作错误信息
    
    # 备注信息
    notes = Column(Text, nullable=True)                     # 备注
    output_metadata = Column(JSONField, nullable=True)      # 扩展元数据
    
    # 关联关系
    materials = relationship("ProductOutputMaterial", back_populates="output", cascade="all, delete-orphan")
    
    # 索引
    __table_args__ = (
        Index('idx_output_product_status', 'product_id', 'status'),
        Index('idx_output_type_quality', 'output_type', 'quality_level'),
        Index('idx_output_approved_published', 'is_approved', 'is_published'),
        Index('idx_output_category', 'category'),
    )
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        result = super().to_dict()
        result['output_type'] = self.output_type.value if self.output_type else None
        result['status'] = self.status.value if self.status else None
        result['quality_level'] = self.quality_level.value if self.quality_level else None
        result['render_settings'] = self.get_render_settings()
        result['export_settings'] = self.get_export_settings()
        result['technical_metrics'] = self.get_technical_metrics()
        result['published_to'] = self.get_published_to()
        result['tags'] = self.get_tags()
        result['metadata'] = self.get_metadata()
        return result
    
    def get_render_settings(self) -> Dict[str, Any]:
        """获取渲染设置"""
        if self.render_settings:
            return json.loads(self.render_settings) if isinstance(self.render_settings, str) else self.render_settings
        return {}
    
    def get_export_settings(self) -> Dict[str, Any]:
        """获取导出设置"""
        if self.export_settings:
            return json.loads(self.export_settings) if isinstance(self.export_settings, str) else self.export_settings
        return {}
    
    def get_technical_metrics(self) -> Dict[str, Any]:
        """获取技术指标"""
        if self.technical_metrics:
            return json.loads(self.technical_metrics) if isinstance(self.technical_metrics, str) else self.technical_metrics
        return {}
    
    def get_published_to(self) -> List[str]:
        """获取发布平台列表"""
        if self.published_to:
            return json.loads(self.published_to) if isinstance(self.published_to, str) else self.published_to
        return []
    
    def get_tags(self) -> List[str]:
        """获取标签列表"""
        if self.tags:
            return json.loads(self.tags) if isinstance(self.tags, str) else self.tags
        return []
    
    def get_metadata(self) -> Dict[str, Any]:
        """获取元数据"""
        if self.output_metadata:
            return json.loads(self.output_metadata) if isinstance(self.output_metadata, str) else self.output_metadata
        return {}
    
    def start_creation(self):
        """开始制作"""
        self.status = OutputStatus.PROCESSING
        self.creation_started_at = datetime.now()
        self.creation_error = None
    
    def complete_creation(self):
        """完成制作"""
        self.status = OutputStatus.COMPLETED
        self.creation_completed_at = datetime.now()
        self.creation_error = None
        
        # 计算制作时长
        if self.creation_started_at:
            delta = self.creation_completed_at - self.creation_started_at
            self.processing_time = delta.total_seconds()
    
    def fail_creation(self, error: str):
        """制作失败"""
        self.status = OutputStatus.FAILED
        self.creation_completed_at = datetime.now()
        self.creation_error = error
    
    def approve(self, approved_by: str, notes: str = None):
        """审核通过"""
        self.is_approved = True
        self.approved_by = approved_by
        self.approved_at = datetime.now()
        self.approval_notes = notes
    
    def publish(self, platforms: List[str] = None):
        """发布成品"""
        self.is_published = True
        self.published_at = datetime.now()
        self.status = OutputStatus.PUBLISHED
        
        if platforms:
            self.published_to = json.dumps(platforms, ensure_ascii=False)
    
    def add_tag(self, tag: str):
        """添加标签"""
        tags = self.get_tags()
        if tag not in tags:
            tags.append(tag)
            self.tags = json.dumps(tags, ensure_ascii=False)
    
    def increment_view(self):
        """增加查看次数"""
        self.view_count += 1
    
    def increment_download(self):
        """增加下载次数"""
        self.download_count += 1
    
    def increment_share(self):
        """增加分享次数"""
        self.share_count += 1
    
    def get_resolution_string(self) -> str:
        """获取分辨率字符串"""
        if self.width and self.height:
            return f"{self.width}x{self.height}"
        return "Unknown"
    
    def get_aspect_ratio(self) -> Optional[float]:
        """获取宽高比"""
        if self.width and self.height and self.height > 0:
            return self.width / self.height
        return None
    
    def get_file_size_mb(self) -> float:
        """获取文件大小(MB)"""
        if self.file_size:
            return self.file_size / (1024 * 1024)
        return 0.0
    
    def is_ready_for_publish(self) -> bool:
        """检查是否可以发布"""
        return (self.status == OutputStatus.COMPLETED and 
                self.is_approved and 
                self.file_path and 
                not self.is_published)
    
    def get_engagement_score(self) -> float:
        """获取参与度评分"""
        # 简单的参与度计算公式
        total_interactions = self.view_count + self.download_count * 5 + self.share_count * 10
        return min(total_interactions / 100.0, 1.0)  # 归一化到0-1
    
    def __repr__(self):
        return f"<ProductOutput(id={self.id}, product_id={self.product_id}, output_id='{self.output_id}', status='{self.status.value if self.status else None}')>"


class ProductOutputMaterial(BaseModel):
    """
    成品-素材关联表

    记录成品中使用的素材和模板视频的对应关系。
    """

    __tablename__ = 'product_output_materials'

    # 关联成品
    output_id = Column(Integer, ForeignKey('product_outputs.id'), nullable=False)
    output = relationship("ProductOutput", back_populates="materials")

    # 关联素材
    material_id = Column(Integer, ForeignKey('product_materials.id'), nullable=False)
    material = relationship("ProductMaterial", back_populates="output_materials")

    # 关联模板视频
    template_video_id = Column(Integer, ForeignKey('template_videos.id'), nullable=True)
    template_video = relationship("TemplateVideo", back_populates="output_materials")

    # 关联模板 (冗余字段，便于查询)
    template_id = Column(Integer, ForeignKey('templates.id'), nullable=True)
    template = relationship("Template", back_populates="output_materials")

    # 使用信息
    usage_order = Column(Integer, nullable=False)           # 使用顺序
    usage_purpose = Column(String(100), nullable=True)      # 使用目的

    # 时间信息
    start_time = Column(Float, nullable=True)               # 在成品中的开始时间
    end_time = Column(Float, nullable=True)                 # 在成品中的结束时间
    duration = Column(Float, nullable=True)                 # 使用时长

    # 素材裁剪信息
    source_start = Column(Float, nullable=True)             # 素材裁剪开始时间
    source_end = Column(Float, nullable=True)               # 素材裁剪结束时间
    source_duration = Column(Float, nullable=True)          # 素材使用时长

    # 变换信息
    transform_x = Column(Float, default=0.0)                # X位置
    transform_y = Column(Float, default=0.0)                # Y位置
    transform_scale_x = Column(Float, default=1.0)          # X缩放
    transform_scale_y = Column(Float, default=1.0)          # Y缩放
    transform_rotation = Column(Float, default=0.0)         # 旋转角度

    # 特效信息
    effects_applied = Column(JSONField, nullable=True)      # 应用的特效
    filters_applied = Column(JSONField, nullable=True)      # 应用的滤镜

    # 音频信息
    audio_volume = Column(Float, default=1.0)               # 音频音量 (0-1)
    audio_fade_in = Column(Float, default=0.0)              # 淡入时长
    audio_fade_out = Column(Float, default=0.0)             # 淡出时长
    is_audio_muted = Column(Boolean, default=False)         # 是否静音

    # 层级信息
    layer_index = Column(Integer, default=0)                # 图层索引
    z_order = Column(Integer, default=0)                    # Z轴顺序

    # 替换信息
    replaced_material_id = Column(String(100), nullable=True)  # 被替换的原始素材ID
    replacement_reason = Column(String(255), nullable=True)    # 替换原因

    # 质量信息
    quality_score = Column(Float, nullable=True)            # 使用质量评分
    fit_score = Column(Float, nullable=True)                # 适配度评分

    # 处理信息
    processing_applied = Column(JSONField, nullable=True)   # 应用的处理
    processing_params = Column(JSONField, nullable=True)    # 处理参数

    # 备注信息
    notes = Column(Text, nullable=True)                     # 备注
    material_metadata = Column(JSONField, nullable=True)    # 扩展元数据

    # 索引
    __table_args__ = (
        Index('idx_output_material_output_order', 'output_id', 'usage_order'),
        Index('idx_output_material_material', 'material_id'),
        Index('idx_output_material_template_video', 'template_video_id'),
        Index('idx_output_material_template', 'template_id'),
        Index('idx_output_material_layer', 'layer_index', 'z_order'),
    )

    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        result = super().to_dict()
        result['effects_applied'] = self.get_effects_applied()
        result['filters_applied'] = self.get_filters_applied()
        result['processing_applied'] = self.get_processing_applied()
        result['processing_params'] = self.get_processing_params()
        result['metadata'] = self.get_metadata()
        return result

    def get_effects_applied(self) -> List[Dict[str, Any]]:
        """获取应用的特效"""
        if self.effects_applied:
            return json.loads(self.effects_applied) if isinstance(self.effects_applied, str) else self.effects_applied
        return []

    def get_filters_applied(self) -> List[Dict[str, Any]]:
        """获取应用的滤镜"""
        if self.filters_applied:
            return json.loads(self.filters_applied) if isinstance(self.filters_applied, str) else self.filters_applied
        return []

    def get_processing_applied(self) -> List[str]:
        """获取应用的处理"""
        if self.processing_applied:
            return json.loads(self.processing_applied) if isinstance(self.processing_applied, str) else self.processing_applied
        return []

    def get_processing_params(self) -> Dict[str, Any]:
        """获取处理参数"""
        if self.processing_params:
            return json.loads(self.processing_params) if isinstance(self.processing_params, str) else self.processing_params
        return {}

    def get_metadata(self) -> Dict[str, Any]:
        """获取元数据"""
        if self.material_metadata:
            return json.loads(self.material_metadata) if isinstance(self.material_metadata, str) else self.material_metadata
        return {}

    def get_transform_info(self) -> Dict[str, float]:
        """获取变换信息"""
        return {
            "x": self.transform_x,
            "y": self.transform_y,
            "scale_x": self.transform_scale_x,
            "scale_y": self.transform_scale_y,
            "rotation": self.transform_rotation
        }

    def get_audio_info(self) -> Dict[str, Any]:
        """获取音频信息"""
        return {
            "volume": self.audio_volume,
            "fade_in": self.audio_fade_in,
            "fade_out": self.audio_fade_out,
            "is_muted": self.is_audio_muted
        }

    def get_time_info(self) -> Dict[str, Optional[float]]:
        """获取时间信息"""
        return {
            "start_time": self.start_time,
            "end_time": self.end_time,
            "duration": self.duration,
            "source_start": self.source_start,
            "source_end": self.source_end,
            "source_duration": self.source_duration
        }

    def calculate_usage_duration(self) -> Optional[float]:
        """计算使用时长"""
        if self.start_time is not None and self.end_time is not None:
            return self.end_time - self.start_time
        return self.duration

    def calculate_source_duration(self) -> Optional[float]:
        """计算源素材使用时长"""
        if self.source_start is not None and self.source_end is not None:
            return self.source_end - self.source_start
        return self.source_duration

    def set_time_range(self, start_time: float, end_time: float):
        """设置时间范围"""
        self.start_time = start_time
        self.end_time = end_time
        self.duration = end_time - start_time

    def set_source_range(self, source_start: float, source_end: float):
        """设置源素材范围"""
        self.source_start = source_start
        self.source_end = source_end
        self.source_duration = source_end - source_start

    def set_transform(self, x: float = None, y: float = None, scale_x: float = None,
                     scale_y: float = None, rotation: float = None):
        """设置变换参数"""
        if x is not None:
            self.transform_x = x
        if y is not None:
            self.transform_y = y
        if scale_x is not None:
            self.transform_scale_x = scale_x
        if scale_y is not None:
            self.transform_scale_y = scale_y
        if rotation is not None:
            self.transform_rotation = rotation

    def set_audio(self, volume: float = None, fade_in: float = None,
                  fade_out: float = None, is_muted: bool = None):
        """设置音频参数"""
        if volume is not None:
            self.audio_volume = max(0.0, min(1.0, volume))  # 限制在0-1范围
        if fade_in is not None:
            self.audio_fade_in = max(0.0, fade_in)
        if fade_out is not None:
            self.audio_fade_out = max(0.0, fade_out)
        if is_muted is not None:
            self.is_audio_muted = is_muted

    def add_effect(self, effect: Dict[str, Any]):
        """添加特效"""
        effects = self.get_effects_applied()
        effects.append(effect)
        self.effects_applied = json.dumps(effects, ensure_ascii=False)

    def add_filter(self, filter_info: Dict[str, Any]):
        """添加滤镜"""
        filters = self.get_filters_applied()
        filters.append(filter_info)
        self.filters_applied = json.dumps(filters, ensure_ascii=False)

    def is_replacement(self) -> bool:
        """判断是否为替换素材"""
        return self.replaced_material_id is not None

    def get_overall_quality_score(self) -> float:
        """获取综合质量评分"""
        scores = []
        if self.quality_score is not None:
            scores.append(self.quality_score)
        if self.fit_score is not None:
            scores.append(self.fit_score)

        return sum(scores) / len(scores) if scores else 0.0

    def __repr__(self):
        return f"<ProductOutputMaterial(id={self.id}, output_id={self.output_id}, material_id={self.material_id}, order={self.usage_order})>"
